import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:geocoding/geocoding.dart';
import 'map_base.dart';
import 'dart:async';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:geolocator/geolocator.dart';
import 'dart:typed_data';

class GMapUtil extends MapBase {
  /// 地图通信中心
  GoogleMapController? _mapController;

  /// 地图创建成功回调
  MapCreatedSuccess? _onMapCallback;

  /// 定位及监听
  final GeolocatorPlatform _geolocatorPlatform = GeolocatorPlatform.instance;
  StreamSubscription<Position>? _locationListener;

  /// 标记点，需要先设置一个空的map赋值给AMapWidget的markers，否则后续无法添加marker
  final Map<MarkerId, Marker> _markers = <MarkerId, Marker>{};

  /// 轨迹线，需要先设置一个空的map赋值给AMapWidget
  Map<PolylineId, Polyline> _polylines = <PolylineId, Polyline>{};

  /// 保存当前轨迹ID，以便修改
  PolylineId? _polylineId;

  /// 保存当前位置的MarkerId，以便修改
  MarkerId? _currentMarkerId;

  /// 防止重复创建
  bool _hasInitMarker = false;

  /// 当前定位标记点
  Marker? _marker;

  /// 定位点ID标记，自动增长
  int _markerNum = 1;

  /// 当前位置
  LatLng markerPosition = const LatLng(39.909187, 116.397451); // 默认位置

  /// 与高德保持同步，- 0.5
  @override
  double get zoom => super.zoom - 0.5;

  /// 隐私权政策是否包含Google开平隐私权政策（高德地图需要，暂时未用到）
  bool? hasContains;

  /// 隐私权政策是否弹窗展示告知用户（高德地图需要，暂时未用到）
  bool? hasShow;

  /// 隐私权政策是否已经取得用户同意（高德地图需要，暂时未用到）
  bool? hasAgree;

  /// 定位成功回调
  LocationModelCallback? locationModelCallback;
  LocationCallback? locationCallback;

  @override
  void initMapConfig(String androidKey, String iosKey,
      {bool? hasContains,
      bool? hasShow,
      bool? hasAgree,
      LatLngCommon? latlng,
      LocationCallback? locationCallback,
      LocationModelCallback? locationModelCallback}) async {
    this.hasContains = hasContains;
    this.hasShow = hasShow;
    this.hasAgree = hasAgree;
    this.locationCallback = locationCallback;
    this.locationModelCallback = locationModelCallback;
    if (latlng != null) {
      markerPosition = LatLng(latlng.latitude, latlng.longitude);
    }

    if (_locationListener == null) {
      final positionStream = _geolocatorPlatform.getPositionStream();
      _locationListener = positionStream.handleError((error) {
        _locationListener?.cancel();
        _locationListener = null;
      }).listen((position) {
        if (locationRepeat != true) {
          stopLocation();
        }

        markerPosition = LatLng(position.latitude, position.longitude);
        LatLngCommon newPosition =
            LatLngCommon(position.latitude, position.longitude);
        print('📍📍📍 --- 当前位置【GMAP】--- $position');
        if (locationCallback != null) {
          locationCallback(newPosition);
        }
      });
      _locationListener?.pause();
    }

    print('📍 --- 注册定位结果监听   $_locationListener');
  }

  @override
  Widget buildMap(BuildContext context, MapCreatedSuccess? onMapCallback,
      {double? width, double? height, bool enableGestureRecognizers = false}) {
    mapHeight = height;
    mapWidth = width;

    this._onMapCallback = onMapCallback;
    final CameraPosition _kGooglePlex = CameraPosition(
      target: LatLng(37.42796133580664, -122.085749655962),
      zoom: zoom,
    );

    // final CameraPosition _kLake = CameraPosition(
    //     bearing: 192.8334901395799,
    //     target: LatLng(37.43296265331129, -122.08832357078792),
    //     tilt: 59.440717697143555,
    //     zoom: 19.151926040649414);

    GoogleMap map = GoogleMap(
      mapType: MapType.normal,
      initialCameraPosition: _kGooglePlex,
      markers: Set<Marker>.of(_markers.values),
      myLocationEnabled: false,
      myLocationButtonEnabled: false,
      polylines: Set<Polyline>.of(_polylines.values), // 添加直线
      onMapCreated: _onMapCreated,
      compassEnabled: compassEnabled,
      rotateGesturesEnabled: gesturesEnabled,
      scrollGesturesEnabled: gesturesEnabled,
      tiltGesturesEnabled: gesturesEnabled,
      zoomGesturesEnabled: gesturesEnabled,

      /// 地图应该使用哪些手势。
      ///
      /// 其他手势识别器可能会在指针上与地图竞争
      /// 事件，例如，如果地图在 [ListView] 内，则 [ListView] 将要处理
      /// 垂直拖动。 地图将声明被任何人识别的手势
      /// 此列表中的识别器。
      ///
      /// 当这个集合为空时，地图将只处理手势的指针事件
      /// 未被任何其他手势识别器声明。
      gestureRecognizers: enableGestureRecognizers
          ? {
              Factory<OneSequenceGestureRecognizer>(
                () => EagerGestureRecognizer(),
              )
            }
          : const <Factory<OneSequenceGestureRecognizer>>{},
    );

    return Container(
      height: mapHeight ?? MediaQuery.of(context).size.height,
      width: mapWidth ?? MediaQuery.of(context).size.width,
      // height: 300,
      // width: MediaQuery.of(context).size.width,
      child: map,
    );
  }

  /// 地图创建成功
  void _onMapCreated(dynamic) {
    this._mapController = dynamic;
    _onMapCallback!(2);
  }

  /// 生成截图
  Future<Uint8List?> takeSnapshot() async {
    return await this._mapController?.takeSnapshot();
  }

  @override
  void startLocation({bool? repeat}) {
    print('开始定位');

    if (_locationListener == null) {
      return;
    }
    locationRepeat = repeat;
    if (_locationListener?.isPaused == true) {
      _locationListener?.resume();
    }
    // else {
    //   _locationListener!.pause();
    // }
  }

  @override
  void stopLocation() {
    print('停止定位');
    _locationListener?.pause();
  }

  @override
  void destroy() {
    print('📍 销毁定位');
    _locationListener?.cancel();
    _locationListener = null;
  }

  @override
  void movePosition(LatLngCommon? latlng, bool animated) {
    LatLng newPosition;
    if (latlng == null) {
      newPosition = markerPosition;
    } else {
      newPosition = LatLng(latlng.latitude, latlng.longitude);
    }

    // 移动地图中心点
    _mapController?.moveCamera(
      CameraUpdate.newCameraPosition(
        CameraPosition(
            //中心点
            target: newPosition,
            //缩放级别
            zoom: zoom,
            //俯仰角0°~45°（垂直与地图时为0）
            tilt: tilt,
            //偏航角 0~360° (正北方为0)
            bearing: bearing),
      ),
    );
  }

  @override
  Future<bool>? initCurrMarker(
      BuildContext context,
      bool showInfoWindow,
      String infoWindowTitle,
      String imageAsset,
      void Function(String value)? onTap) async {
    if (_hasInitMarker) {
      return false;
    }

    final MarkerId markerId = MarkerId('currMarkerValue');
    BitmapDescriptor? _markerIcon = await _createMarkerImageFromAsset(
        context, imageAsset); //'images/marker_icon.png'
    _marker = Marker(
      markerId: markerId,
      position: markerPosition,
      infoWindow: InfoWindow(title: '实时位置'),
      icon: _markerIcon!,
      onTap: () {
        // _onMarkerTapped(markerId);
      },
      onDragEnd: (LatLng position) {
        // _onMarkerDragEnd(markerId, position);
      },
    );

    // 需要调用setState才能显示
    _currentMarkerId = markerId;
    _markers[markerId] = _marker!;
    _hasInitMarker = true;

    return true;
  }

  @override
  void updateCurrMarker() {
    // 修改当前标记点位置
    if (_currentMarkerId != null) {
      _markers[_currentMarkerId!] = _marker!.copyWith(
        positionParam: markerPosition,
      );
    }
  }

  @override
  void initLine(BuildContext context, List<LatLngCommon> latlngList,
      double width, void Function(String value) onTap) {
    List<LatLng> newPoints = getLatLngPoints(latlngList);
    _polylineId = PolylineId('polylineIdVal');
    final Polyline polyline = Polyline(
      polylineId: _polylineId!,
      consumeTapEvents: true,
      color: polylineColor,
      width: 7,
      points: newPoints,
      startCap: Cap.roundCap,
      endCap: Cap.roundCap,
      onTap: () {
        // _onPolylineTapped(polylineId!);
      },
    );

    // 需要调用setState才能显示
    _polylines[_polylineId!] = polyline;
  }

  /// 转换坐标数组
  List<LatLng> getLatLngPoints(List<LatLngCommon> points) {
    List<LatLng> newPoints = <LatLng>[];
    //   List newList2 = listArr2.map((value){
    //   return value*2;
    // });
    // 将数据LatLngCommon修改为LatLng
    newPoints =
        points.map((point) => LatLng(point.latitude, point.longitude)).toList();
    return newPoints;
  }

  /// 创建自定义Marker Icon
  Future<BitmapDescriptor?> _createMarkerImageFromAsset(
      BuildContext context, String imageAsset) async {
    final ImageConfiguration imageConfiguration = createLocalImageConfiguration(
        context); //(context, size: Size.square(48))
    BitmapDescriptor? _markerIcon =
        await BitmapDescriptor.fromAssetImage(imageConfiguration, imageAsset);
    return _markerIcon;
  }

  @override
  Future<String> getGeocodeAddress(LatLngCommon latlng) async {
    print('Google地图逆地理编码申请');
    List<Placemark> placemarks =
        await placemarkFromCoordinates(latlng.latitude, latlng.longitude);
    Placemark placemark = placemarks.first;
    return '${placemark.country}${placemark.administrativeArea}${placemark.locality}${placemark.subLocality}${placemark.street}';
  }

  @override
  void clearMarkers({String? id}) {
    if (id != null) {
      _markers.remove(id);
    } else {
      _markers.clear();
    }
  }

  @override
  MapClassType getMapType() {
    return MapClassType.google;
  }

  @override
  Future addMarker(
    BuildContext context,
    LatLngCommon latlng,
    bool showInfoWindow,
    String infoWindowTitle,
    String imageAsset,
    void Function(String p1)? onTap, {
    double rotation = 0.0,
    void Function(String)? callbackMarkId,
  }) async {
    LatLng newPoint = LatLng(latlng.latitude, latlng.longitude);
    BitmapDescriptor? markerIcon =
        await _createMarkerImageFromAsset(context, imageAsset);
    final MarkerId markerId = MarkerId('AddMarkerValue_$_markerNum');

    if (callbackMarkId != null) {
      callbackMarkId(markerId.value);
    }
    _markerNum += 1;
    if (showInfoWindow == true) {
      final Marker marker = Marker(
          markerId: markerId,
          position: newPoint,
          infoWindow: InfoWindow(title: infoWindowTitle),
          icon: markerIcon!);

      // 需要调用setState才能显示
      _markers[markerId] = marker;
    } else {
      final Marker marker =
          Marker(markerId: markerId, position: newPoint, icon: markerIcon!);

      // 需要调用setState才能显示
      _markers[markerId] = marker;
    }
  }
}
